﻿using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Service.Auth.Model.Model;
using Service.Core.Filters;
using Service.Core.Identity;
using Service.Core.Identity.Model;
using Service.Core.Redis.DistributedLock;
using Service.Core.Redis.Services;
using Service.Core.Utils.Sms;
using Service.Core.Utils.VerificationCodeUtil;
using Service.Framework;
using Service.Framework.OperationLog;
using Service.Framework.Utils;
using Service.Framework.Utils.Helper;

namespace Service.Auth.Api.Controller
{
    /// <summary>
    /// 登陆控制器
    /// </summary>
    [AllowAnonymous]
    public class LoginController(
        IMediator mediator, ClientService clientService,
        IRedisService redisService,
        ISmsService smsService,
        IDistributedLockService distributedLockService)
        : BaseController(mediator)
    {


        /// <summary>
        /// 账号密码登陆
        /// </summary>
        /// <param name="passwordTokenRequest"></param>
        /// <returns></returns>
        [HttpPost]
        [OperateLogFilter("登录日志", "账号密码登陆", OperationLogType.Login, "登陆成功", nameof(CustomPasswordTokenRequest.Password))]
        public async Task<CustomTokenResponse> Login([FromBody] CustomPasswordTokenRequest passwordTokenRequest)
        {
            return await clientService.GetAccessTokenByPasswordToken(passwordTokenRequest);
        }

        /// <summary>
        /// sms短信验证码登陆
        /// </summary>
        /// <param name="smsTokenRequest"></param>
        /// <returns></returns>
        [HttpPost]
        [OperateLogFilter("登录日志", "验证码登陆", OperationLogType.Login, "登陆成功")]

        public async Task<CustomTokenResponse> LoginBySms([FromBody] CustomSmsTokenRequest smsTokenRequest)
        {
            return await clientService.GetAccessTokenBySms(smsTokenRequest);
        }


        /// <summary>
        /// token刷新
        /// </summary>
        /// <param name="customRefreshTokenRequest"></param>
        /// <returns></returns>
        [HttpPost]
        [OperateLogFilter("登录日志", "刷新Token", OperationLogType.Login, "登陆成功")]
        public async Task<CustomTokenResponse> RefreshToken([FromBody] CustomRefreshTokenRequest customRefreshTokenRequest)
        {
            return await clientService.GetAccessTokenByRefreshToken(customRefreshTokenRequest);
        }


        /// <summary>
        /// 获取混合式图片验证码
        /// </summary>
        /// <param name="verificationCodeService"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<VerfyCodeVo> HybridImgVerificationCode(
            [FromKeyedServices(VerificationCodeTypeEnum.HybridImg)] IVerificationCodeService verificationCodeService)
        {
            var id = SnowflakeUtil.Instance().GetId().ToString();
            var verfyCode = await verificationCodeService.CreateVerificationCode();
            //验证码存在60秒
            await redisService.Database.StringSetAsync(id, verfyCode.Code, TimeSpan.FromSeconds(60));
            return new VerfyCodeVo(id, "data:image/png;base64," + Convert.ToBase64String(verfyCode.VerfyByte));
        }


        /// <summary>
        /// 发送登陆短信验证码，使用ip做限流,做黑名单
        /// </summary>
        /// <param name="smsLoginDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<bool> SendSmsLoginCode([FromBody] SmsLoginDto smsLoginDto)
        {
            var phone = smsLoginDto.Phone;
            if (phone.IsNullOrEmpty() || phone.Length != 11)
            {
                throw new LogicErrorException("手机号错误，请检查手机号码是否合法。");
            }

            var key = $"{nameof(SendSmsLoginCode)}:{phone}";
            var countKey = $"{nameof(SendSmsLoginCode)}:{phone}-count";

            var redisCount = await redisService.Database.StringGetWithExpiryAsync(countKey);
            var count = 1;
            if (redisCount.Value.HasValue)
            {
                count = (int)redisCount.Value;
                if (count >= 1)
                {
                    throw new LogicErrorException("1分钟内只能发送一次验证码，请稍后再试。");
                }
            }
            var code = CreateMixVerifyCode(6);
            var minutes = 5;
            var result = await smsService.SendSms(phone, "SendSmsLoginCode", code, minutes.ToString());
            if (result)
            {
                await redisService.Database.StringSetAsync(key, code, TimeSpan.FromMinutes(minutes));
                count += 1;
                await redisService.Database.StringSetAsync(countKey, count, redisCount.Expiry ?? TimeSpan.FromMinutes(1));
            }
            return result;
        }

        /// <summary>
        /// 3.混合验证码
        /// </summary>
        /// <param name="length">字符长度</param>
        /// <returns>验证码字符</returns>
        private string CreateMixVerifyCode(int length)
        {
            char[] verification = new char[length];
            char[] dictionary = {
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
   };
            Random random = new Random();
            for (int i = 0; i < length; i++)
            {
                verification[i] = dictionary[random.Next(dictionary.Length - 1)];
            }
            return new string(verification);
        }


    }
}